home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gscolor.c < prev    next >
C/C++ Source or Header  |  1997-04-24  |  11KB  |  367 lines

  1. /* Copyright (C) 1989, 1992, 1993, 1994, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gscolor.c */
  20. /* Color and halftone operators for Ghostscript library */
  21. #include "gx.h"
  22. #include "gserrors.h"
  23. #include "gsstruct.h"
  24. #include "gsutil.h"            /* for gs_next_ids */
  25. #include "gsccolor.h"
  26. #include "gxcspace.h"
  27. #include "gxdcconv.h"
  28. #include "gxdevice.h"            /* for gx_color_index */
  29. #include "gxcmap.h"
  30. #include "gzstate.h"
  31.  
  32. /* Imported from gsht.c */
  33. void gx_set_effective_transfer(P1(gs_state *));
  34.  
  35. /* Define the standard color space types. */
  36. extern cs_proc_remap_color(gx_remap_DeviceGray);
  37. extern cs_proc_concretize_color(gx_concretize_DeviceGray);
  38. extern cs_proc_remap_concrete_color(gx_remap_concrete_DGray);
  39. extern cs_proc_remap_color(gx_remap_DeviceRGB);
  40. extern cs_proc_concretize_color(gx_concretize_DeviceRGB);
  41. extern cs_proc_remap_concrete_color(gx_remap_concrete_DRGB);
  42. const gs_color_space_type
  43.     gs_color_space_type_DeviceGray =
  44.      { gs_color_space_index_DeviceGray, 1, true,
  45.        gx_init_paint_1, gx_same_concrete_space,
  46.        gx_concretize_DeviceGray, gx_remap_concrete_DGray,
  47.        gx_remap_DeviceGray, gx_no_install_cspace,
  48.        gx_no_adjust_cspace_count, gx_no_adjust_color_count,
  49.        gx_no_cspace_enum_ptrs, gx_no_cspace_reloc_ptrs
  50.      },
  51.     gs_color_space_type_DeviceRGB =
  52.      { gs_color_space_index_DeviceRGB, 3, true,
  53.        gx_init_paint_3, gx_same_concrete_space,
  54.        gx_concretize_DeviceRGB, gx_remap_concrete_DRGB,
  55.        gx_remap_DeviceRGB, gx_no_install_cspace,
  56.        gx_no_adjust_cspace_count, gx_no_adjust_color_count,
  57.        gx_no_cspace_enum_ptrs, gx_no_cspace_reloc_ptrs
  58.      };
  59.  
  60. /* Structure descriptors */
  61. public_st_color_space();
  62. public_st_client_color();
  63.  
  64. /*
  65.  * Define permanent instances of the 3 device color spaces.
  66.  * The one for CMYK is initialized by gscolor1.c and may be NULL.
  67.  */
  68. const gs_color_space *gs_cs_static_DeviceGray;
  69. private gs_gc_root_t cs_gray_root;
  70. const gs_color_space *gs_cs_static_DeviceRGB;
  71. private gs_gc_root_t cs_rgb_root;
  72. const gs_color_space *gs_cs_static_DeviceCMYK = 0;
  73. private gs_gc_root_t cs_cmyk_root;
  74. void
  75. gs_gscolor_init(gs_memory_t *mem)
  76. {
  77. #define cs_init(cs_var, cs_type, cname)\
  78.   { gs_color_space *pcs =\
  79.       gs_alloc_struct(mem, gs_color_space, &st_color_space, cname);\
  80.     pcs->type = &cs_type;\
  81.     cs_var = pcs;\
  82.   }
  83.     cs_init(gs_cs_static_DeviceGray, gs_color_space_type_DeviceGray,
  84.         "gs_cs_static_DeviceGray");
  85.     gs_register_struct_root(mem, &cs_gray_root,
  86.                 (void **)&gs_cs_static_DeviceGray,
  87.                 "gs_cs_static_DeviceGray");
  88.     cs_init(gs_cs_static_DeviceRGB, gs_color_space_type_DeviceRGB,
  89.         "gs_cs_static_DeviceRGB");
  90.     gs_register_struct_root(mem, &cs_rgb_root,
  91.                 (void **)&gs_cs_static_DeviceRGB,
  92.                 "gs_cs_static_DeviceRGB");
  93.     gs_register_struct_root(mem, &cs_cmyk_root,
  94.                 (void **)&gs_cs_static_DeviceCMYK,
  95.                 "gs_cs_static_DeviceCMYK");
  96. #undef cs_init
  97. }
  98. const gs_color_space *
  99. gs_color_space_DeviceGray(void)
  100. {    return gs_cs_static_DeviceGray;
  101. }
  102. const gs_color_space *
  103. gs_color_space_DeviceRGB(void)
  104. {    return gs_cs_static_DeviceRGB;
  105. }
  106. const gs_color_space *
  107. gs_color_space_DeviceCMYK(void)
  108. {    return gs_cs_static_DeviceCMYK;
  109. }
  110.  
  111. /* Get the index of a color space. */
  112. gs_color_space_index
  113. gs_color_space_get_index(const gs_color_space *pcs)
  114. {    return pcs->type->index;
  115. }
  116.  
  117. /* Get the number of components in a color space. */
  118. int
  119. gs_color_space_num_components(const gs_color_space *pcs)
  120. {    return pcs->type->num_components;
  121. }
  122.  
  123. /* Get the base space of an Indexed color space. */
  124. const gs_color_space *
  125. gs_color_space_indexed_base_space(const gs_color_space *pcs)
  126. {    return (const gs_color_space *)&pcs->params.indexed.base_space;
  127. }
  128.  
  129. /* Initialize colors with 1, or 3, or 4 paint components. */
  130. /* (These are only used by setcolorspace.) */
  131. void
  132. gx_init_paint_1(gs_client_color *pcc, const gs_color_space *pcs)
  133. {    pcc->paint.values[0] = 0.0;
  134. }
  135. void
  136. gx_init_paint_3(gs_client_color *pcc, const gs_color_space *pcs)
  137. {    pcc->paint.values[2] = 0.0;
  138.     pcc->paint.values[1] = 0.0;
  139.     pcc->paint.values[0] = 0.0;
  140. }
  141. void
  142. gx_init_paint_4(gs_client_color *pcc, const gs_color_space *pcs)
  143. {    /* DeviceCMYK and CIEBasedDEFG spaces initialize to 0,0,0,1. */
  144.     pcc->paint.values[3] = 1.0;
  145.     gx_init_paint_3(pcc, pcs);
  146. }
  147.  
  148. /* Null color space installation procedure. */
  149. int
  150. gx_no_install_cspace(gs_color_space *pcs, gs_state *pgs)
  151. {    return 0;
  152. }
  153.  
  154. /* Null reference count adjustment procedures. */
  155. void
  156. gx_no_adjust_cspace_count(const gs_color_space *pcs, gs_memory_t *mem,
  157.   int delta)
  158. {
  159. }
  160. void
  161. gx_no_adjust_color_count(const gs_client_color *pcc, const gs_color_space *pcs, gs_memory_t *mem, int delta)
  162. {
  163. }
  164.  
  165. /* GC procedures */
  166.  
  167. #define pcs ((gs_color_space *)vptr)
  168.  
  169. private ENUM_PTRS_BEGIN_PROC(color_space_enum_ptrs) {
  170.     return (*pcs->type->enum_ptrs)(pcs, size, index, pep);
  171. ENUM_PTRS_END_PROC }
  172. private RELOC_PTRS_BEGIN(color_space_reloc_ptrs) {
  173.     (*pcs->type->reloc_ptrs)(pcs, size, gcst);
  174. } RELOC_PTRS_END
  175.  
  176. #undef pcs
  177.  
  178. /* Force a parameter into the range [0.0..1.0]. */
  179. #define force_unit(p) (p < 0.0 ? 0.0 : p > 1.0 ? 1.0 : p)
  180.  
  181. /* Forward declarations */
  182. void load_transfer_map(P3(gs_state *, gx_transfer_map *, floatp));
  183.  
  184. /* setgray */
  185. int
  186. gs_setgray(gs_state *pgs, floatp gray)
  187. {    if ( pgs->in_cachedevice ) return_error(gs_error_undefined);
  188.     cs_adjust_counts(pgs, -1);
  189.     pgs->ccolor->paint.values[0] = gray;
  190.     pgs->color_space->type = &gs_color_space_type_DeviceGray;
  191.     gx_unset_dev_color(pgs);
  192.     return 0;
  193. }
  194.  
  195. /* currentgray */
  196. float
  197. gs_currentgray(const gs_state *pgs)
  198. {    const gs_client_color *pcc = pgs->ccolor;
  199.     switch ( pgs->color_space->type->index )
  200.     {
  201.     case gs_color_space_index_DeviceGray:
  202.         return pcc->paint.values[0];
  203.     case gs_color_space_index_DeviceRGB:
  204.         return frac2float(color_rgb_to_gray(
  205.             float2frac(pcc->paint.values[0]),
  206.             float2frac(pcc->paint.values[1]),
  207.             float2frac(pcc->paint.values[2]),
  208.             (const gs_imager_state *)pgs));
  209.     case gs_color_space_index_DeviceCMYK:
  210.         return frac2float(color_cmyk_to_gray(
  211.             float2frac(pcc->paint.values[0]),
  212.             float2frac(pcc->paint.values[1]),
  213.             float2frac(pcc->paint.values[2]),
  214.             float2frac(pcc->paint.values[3]),
  215.             (const gs_imager_state *)pgs));
  216.     default:
  217.         return 0.0;
  218.     }
  219. }
  220.  
  221. /* setrgbcolor */
  222. int
  223. gs_setrgbcolor(gs_state *pgs, floatp r, floatp g, floatp b)
  224. {    gs_client_color *pcc = pgs->ccolor;
  225.     if ( pgs->in_cachedevice ) return_error(gs_error_undefined);
  226.     cs_adjust_counts(pgs, -1);
  227.     pcc->paint.values[0] = r;
  228.     pcc->paint.values[1] = g;
  229.     pcc->paint.values[2] = b;
  230.     pcc->pattern = 0;            /* for GC */
  231.     pgs->color_space->type = &gs_color_space_type_DeviceRGB;
  232.     gx_unset_dev_color(pgs);
  233.     return 0;
  234. }
  235.  
  236. /* currentrgbcolor */
  237. int
  238. gs_currentrgbcolor(const gs_state *pgs, float pr3[3])
  239. {    const gs_client_color *pcc = pgs->ccolor;
  240.     switch ( pgs->color_space->type->index )
  241.     {
  242.     case gs_color_space_index_DeviceGray:
  243.         pr3[0] = pr3[1] = pr3[2] = pcc->paint.values[0];
  244.         break;
  245.     case gs_color_space_index_DeviceRGB:
  246.         pr3[0] = pcc->paint.values[0];
  247.         pr3[1] = pcc->paint.values[1];
  248.         pr3[2] = pcc->paint.values[2];
  249.         break;
  250.     case gs_color_space_index_DeviceCMYK:
  251.     {    frac frgb[3];
  252.         color_cmyk_to_rgb(
  253.             float2frac(pcc->paint.values[0]),
  254.             float2frac(pcc->paint.values[1]),
  255.             float2frac(pcc->paint.values[2]),
  256.             float2frac(pcc->paint.values[3]),
  257.             (const gs_imager_state *)pgs, frgb);
  258.         pr3[0] = frac2float(frgb[0]);
  259.         pr3[1] = frac2float(frgb[1]);
  260.         pr3[2] = frac2float(frgb[2]);
  261.     }    break;
  262.     default:
  263.         pr3[0] = pr3[1] = pr3[2] = 0.0;
  264.     }
  265.     return 0;
  266. }
  267.  
  268. /* setalpha */
  269. int
  270. gs_setalpha(gs_state *pgs, floatp alpha)
  271. {    pgs->alpha = (gx_color_value)(force_unit(alpha) * gx_max_color_value);
  272.     gx_unset_dev_color(pgs);
  273.     return 0;
  274. }
  275.  
  276. /* currentalpha */
  277. float
  278. gs_currentalpha(const gs_state *pgs)
  279. {    return (float)pgs->alpha / gx_max_color_value;
  280. }
  281.  
  282. /* setnullcolor */
  283. int
  284. gs_setnullcolor(gs_state *pgs)
  285. {    if ( pgs->in_cachedevice )
  286.       return_error(gs_error_undefined);
  287.     gs_setgray(pgs, 0.0);    /* set color space to something harmless */
  288.     color_set_null(pgs->dev_color);
  289.     return 0;
  290. }
  291.  
  292. /* settransfer */
  293. /* Remap=0 is used by the interpreter. */
  294. int
  295. gs_settransfer(gs_state *pgs, gs_mapping_proc tproc)
  296. {    return gs_settransfer_remap(pgs, tproc, true);
  297. }
  298. int
  299. gs_settransfer_remap(gs_state *pgs, gs_mapping_proc tproc, bool remap)
  300. {    gx_transfer_colored *ptran = &pgs->set_transfer.colored;
  301.     /* We can safely decrement the reference counts */
  302.     /* of the non-gray transfer maps, because */
  303.     /* if any of them get freed, the rc_unshare can't fail. */
  304.     rc_decrement(ptran->red, "gs_settransfer");
  305.     rc_decrement(ptran->green, "gs_settransfer");
  306.     rc_decrement(ptran->blue, "gs_settransfer");
  307.     rc_unshare_struct(ptran->gray, gx_transfer_map, &st_transfer_map,
  308.               pgs->memory, goto fail, "gs_settransfer");
  309.     ptran->gray->proc = tproc;
  310.     ptran->gray->id = gs_next_ids(1);
  311.     ptran->red = ptran->gray;
  312.     ptran->green = ptran->gray;
  313.     ptran->blue = ptran->gray;
  314.     ptran->gray->rc.ref_count += 3;
  315.     if ( remap )
  316.     {    load_transfer_map(pgs, ptran->gray, 0.0);
  317.         gx_set_effective_transfer(pgs);
  318.         gx_unset_dev_color(pgs);
  319.     }
  320.     return 0;
  321. fail:    rc_increment(ptran->red);
  322.     rc_increment(ptran->green);
  323.     rc_increment(ptran->blue);
  324.     return_error(gs_error_VMerror);
  325. }
  326.  
  327. /* currenttransfer */
  328. gs_mapping_proc
  329. gs_currenttransfer(const gs_state *pgs)
  330. {    return pgs->set_transfer.colored.gray->proc;
  331. }
  332.  
  333. /* ------ Non-operator routines ------ */
  334.  
  335. /* Set device color = 1 for writing into the character cache. */
  336. void
  337. gx_set_device_color_1(gs_state *pgs)
  338. {    gx_device_color *pdc = pgs->dev_color;
  339.     gs_client_color *pcc = pgs->ccolor;
  340.     cs_adjust_counts(pgs, -1);
  341.     pcc->paint.values[0] = 0.0;
  342.     pcc->pattern = 0;            /* for GC */
  343.     pgs->color_space->type = &gs_color_space_type_DeviceGray;
  344.     color_set_pure(pdc, 1);
  345.     pgs->log_op = lop_default;
  346. }
  347.  
  348. /* ------ Internal routines ------ */
  349.  
  350. /* Load one cached transfer map. */
  351. /* This is exported for gscolor1.c. */
  352. void
  353. load_transfer_map(gs_state *pgs, gx_transfer_map *pmap, floatp min_value)
  354. {    gs_mapping_proc proc = pmap->proc;
  355.     frac *values = pmap->values;
  356.     frac fmin = float2frac(min_value);
  357.     int i;
  358.     for ( i = 0; i < transfer_map_size; i++ )
  359.     {    float fval =
  360.             (*proc)((float)i / (transfer_map_size - 1), pmap);
  361.         values[i] =
  362.             (fval < min_value ? fmin :
  363.              fval >= 1.0 ? frac_1 :
  364.              float2frac(fval));
  365.     }
  366. }
  367.